package client;

import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.net.BindException;
import java.net.ConnectException;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.Socket;
import java.net.SocketTimeoutException;
import java.net.UnknownHostException;

import shared.Packet0Connect;

import client.gui.SettingsGUI;

public class ConnectionThread extends Thread{
    TestingClient host;

    public int serverPort = 32001;
    public String name = "Temp";
    public String destination = "192.168.1.1";
    public boolean autoConnect = false;

    public ConnectionThread(TestingClient host, int serverPort, String name, String destination, boolean autoConnect){
        this.host = host;
        this.serverPort = serverPort;
        this.name = name;
        this.destination = destination;
        this.autoConnect = autoConnect;
    }

    public void run(){
        String address = "";

        host.clientGUI.addLine("Current name: " + name);
        try {
            address = InetAddress.getLocalHost().getHostAddress();
            host.clientGUI.addLine("Current address: " + address);
        } catch (UnknownHostException e2) {
            e2.printStackTrace();
        }

        if(!autoConnect){
            if (!directConnect(destination, serverPort)){
                host.clientGUI.addLine("Connection failed.");
                host.clientGUI.setInputFieldEnabled(false);
                new SettingsGUI(host).setVisible(true);
                return;
            }
        }else{
            if(!autoConnect(address, serverPort)){
                host.clientGUI.addLine("Connection failed.");
                host.clientGUI.setInputFieldEnabled(false);
                new SettingsGUI(host).setVisible(true);
                return;
            }
        }

        try {
            host.out = new ObjectOutputStream(host.clientSocket.getOutputStream());
            host.in = new ObjectInputStream(host.clientSocket.getInputStream());
            host.out.flush();

            host.receive = new ReceivePacketThread(host);
            host.receive.start();

            host.packetHandler.sendPacket(new Packet0Connect(name));
            host.isConnected = true;
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public boolean directConnect(String dest, int port) {
        try {
            host.clientGUI.addLine("Attempting connection to " + dest);
            host.clientSocket = new Socket();
            host.clientSocket.connect(new InetSocketAddress(dest, port), 1000);
            host.clientGUI.addLine("Connected to " + dest + " in port " + port);
            return true;
        } catch (SocketTimeoutException e) {
            // There is no server on the given address
        } catch (UnknownHostException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
        try {
            host.clientSocket.close();
            host.clientSocket = null;
        } catch (IOException ex) {
            ex.printStackTrace();
        }
        return false;
    }

    public boolean autoConnect(String currentAddress, int port) {
        host.clientGUI.addLine("Attempting to automatically obtain address.");
        int timeout = 15;
        String[] addressSections;
        int[] addressSectionsInt;

        addressSections = currentAddress.split("\\.");
        addressSectionsInt = new int[addressSections.length];
        for (int a = 0; a < addressSections.length; a++) {
            addressSectionsInt[a] = Integer.parseInt(addressSections[a]);
        }

        int iTemp = addressSectionsInt[addressSectionsInt.length - 2];
        for (int a = -1; a < 256; a++) {
            if (a == -1); else if (a == iTemp) {
                a++;
                addressSectionsInt[addressSectionsInt.length - 2] = a;
            } else {
                addressSectionsInt[addressSectionsInt.length - 2] = a;
            }
            for (int b = 0; b < 256; b++) {
                addressSectionsInt[addressSectionsInt.length - 1] = b;
                String temp = formAddress(addressSectionsInt);
                try {
                    //host.clientGUI.addLine("Attempting connection to " + temp);
                    host.clientSocket = new Socket();
                    host.clientSocket.connect(new InetSocketAddress(temp, port), timeout);
                    host.clientGUI.addLine("Connected to " + temp + " in port " + port);
                    return true;
                } catch (SocketTimeoutException e) {
                    //host.clientGUI.addLine("Failed. Retrying, ");
                } catch (BindException e) {
                    host.clientGUI.addLine("BindException.");
                    return false;
                } catch (UnknownHostException e) {
                    host.clientGUI.addLine("UnknownHostException Connection failed.");
                    return false;
                } catch (ConnectException e) {
                    host.clientGUI.addLine("ConnectException.");
                    return false;
                } catch (IOException e) {
                    e.printStackTrace();
                    host.clientGUI.addLine("IOException Connection failed. Retrying.");
                }
            }
        }
        return false;
    }

    public String formAddress(int[] input) {
        String result = "";
        for (int a = 0; a < input.length; a++) {
            result += input[a] + (a + 1 < input.length ? "." : "");
        }
        return result;
    }
}
